package com.fw4j.jdbc.factory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import com.fw4j.jdbc.annotation.Column;
import com.fw4j.jdbc.annotation.Entity;
import com.fw4j.jdbc.annotation.Table;
import com.fw4j.jdbc.exception.InstanceException;
import com.fw4j.jdbc.tools.CreateEntity;


/**
 * @author 穆仁超
 * 创建Entity工厂
 * 日期 2013-12-27 16:34
 * 我的QQ群：32894018
 */
public class EntityFactory{
	public static <T> T getInstance(Class<T> cl) throws InstanceException{
		if(cl.isInterface()){
			CreateEntity ce = new CreateEntity();
			Annotation[] as = cl.getAnnotations();
			Entity ey = null;
			Table tl = null;
			for(Annotation a : as){
				if(a instanceof Entity){
					ey = (Entity)a;
				}else if(a instanceof Table){
					tl = (Table)a;
				}//end if
			}//end if
			if(tl== null || ey == null){
				throw new InstanceException("class "+cl.getName()+"is not Entity");
			}
			String className = tl.value();
			Object obj = ce.getInstance(className);
			if(obj != null){
				return (T)obj;
			}
			if(tl!=null && ey != null){
				ce.createClass(className,null, new String[]{cl.getName().replace(".", "/")});
				Method[] ms = cl.getMethods();
				Column cn = null;
				String field = null;
				Set<String> methodLog = new HashSet<String>();
				for(Method m : ms){
					StringBuffer methodName = new StringBuffer(m.getName());
					for(Annotation a : m.getAnnotations()){
						if(a instanceof Column){
							cn = (Column)a;
							field = cn.value();
						}
					}
					if(cn != null){
						cn = null;
						String method = methodName.substring(3).trim().toLowerCase();
						if(methodName.toString().startsWith("set") && !methodLog.contains(method)){
							Class type = m.getParameterTypes()[0];
							methodLog.add(field.toLowerCase());
							ce.addField(field,type);
							StringBuffer mhd = new StringBuffer(m.getReturnType().getName().replace(".", "/"));
							mhd.append(" ");
							mhd.append(methodName.toString());
							mhd.append(" (");
							mhd.append(type.getName().replace(".", "/"));
							mhd.append(")");
							ce.addSetter(mhd.toString(),field, type);
							
							mhd = new StringBuffer(type.getName().replace(".", "/"));
							mhd.append(" ");
							mhd.append(methodName.replace(0, 3, "get").toString());
							mhd.append(" ()");
							ce.addGetter(mhd.toString(),field, type);
						}else if(methodName.toString().startsWith("get") && !methodLog.contains(method)){
							Class type = m.getReturnType();
							methodLog.add(field.toLowerCase());
							ce.addField(field,type);
							
							StringBuffer mhd = new StringBuffer("void ");
							mhd.append(" ");
							mhd.append(methodName.replace(0, 3, "set").toString());
							mhd.append(" (");
							mhd.append(type.getName().replace(".", "/"));
							mhd.append(")");
							ce.addSetter(mhd.toString(),field, type);
							
							mhd = new StringBuffer(type.getName().replace(".", "/"));
							mhd.append(" ");
							mhd.append(methodName.replace(0, 3, "get").toString());
							mhd.append(" ()");
							ce.addGetter(mhd.toString(),field, type);
						}
					}//end if
				}//end for
				return (T)ce.loadClass();
			}//end if
		}//end if
		return null;
	}
}
